package com.lmn.statemachine;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.transition.Transition;
import org.springframework.statemachine.transition.TransitionKind;

import java.util.EnumSet;

/**
 * 1. 状态机的初始状态和所有状态
 * 2. 状态之间的转移规则
 */
@Configuration
@EnableStateMachine
public class CompanyStateMachineConfig extends EnumStateMachineConfigurerAdapter<CompanyStatus, CompanyEvents> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<CompanyStatus, CompanyEvents> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
                .listener(listener());
    }

    @Override
    public void configure(StateMachineStateConfigurer<CompanyStatus, CompanyEvents> states) throws Exception {
        states.withStates()
                // 定义初始状态
                .initial(CompanyStatus.WAIT_PERSON_REAL_NAME)
                // 定义所有状态集合
                .states(EnumSet.allOf(CompanyStatus.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<CompanyStatus, CompanyEvents> transitions) throws Exception {
        transitions.withExternal()
                .source(CompanyStatus.WAIT_PERSON_REAL_NAME)
                .target(CompanyStatus.WAIT_COMPANT_REAL_NAME)
                .event(CompanyEvents.PERSON_REAL_NAME)
                .guard(new PersonRealNameGuard())
                .action(new PersonRealNameAction(), new PersonRealNameErrorAction())
                .and()

                .withExternal()
                .source(CompanyStatus.WAIT_COMPANT_REAL_NAME)
                .target(CompanyStatus.FINISH_REAL_NAME)
                .event(CompanyEvents.COMPANY_REAL_NAME);
    }

    @Bean
    public StateMachineListener<CompanyStatus, CompanyEvents> listener() {
        return new StateMachineListenerAdapter<>() {
            @Override
            public void stateMachineStarted(StateMachine<CompanyStatus, CompanyEvents> stateMachine) {
                System.out.println("开始：" + stateMachine.getState().getId());
            }

            @Override
            public void transitionStarted(Transition<CompanyStatus, CompanyEvents> transition) {
                if (TransitionKind.INITIAL.equals(transition.getKind())) {
                    System.out.println("-----transitionStarted - INIT---");
                    return;
                }
                System.out.println("pre状态从  " + transition.getSource().getId() + "  改变为  " + transition.getTarget().getId());
            }

            @Override
            public void transition(Transition<CompanyStatus, CompanyEvents> transition) {
                if (TransitionKind.INITIAL.equals(transition.getKind())) {
                    System.out.println("-----transition - INITIAL---");
                    return;
                }
                System.out.println("post状态从  " + transition.getSource().getId() + "  改变为  " + transition.getTarget().getId());
            }


            @Override
            public void transitionEnded(Transition<CompanyStatus, CompanyEvents> transition) {
                if (TransitionKind.INITIAL.equals(transition.getKind())) {
                    System.out.println("-----transitionEnded - INITIAL----");
                    return;
                }
                System.out.println("end状态从  " + transition.getSource().getId() + "  改变为  " + transition.getTarget().getId());
            }
        };
    }
}